home *** CD-ROM | disk | FTP | other *** search
- program lander;
-
- const
- instrfile = 'LANDINST.DAT';
- maxrand = 32767;
- timeinc = 0.1;
- slightly = 0.1;
- moderately = 0.2;
- very = 0.3;
- impossible = 0.5;
- certainty = 1.0;
- minmeteors = 2.0;
- maxmeteors = 7.0;
- eachmisschance = 0.8;
- minavoid = 10;
- landingheight = 0.1;
- crashlandspeed = 6.0;
-
- type
- answers = set of 'A'..'Z';
- str80 = string[80];
-
- var
- speed, height, gravity : real;
- maxlandingspeed : real;
- chance, misschance : real;
- burn, fuel : integer;
- nummeteors : integer;
- inp : string[10];
- ranout : boolean;
-
- (*
- * returns a random real number between lowlimit and highlimit
- *)
-
- function rand(lowlimit, highlimit : real) : real;
-
- begin
- rand := lowlimit + (highlimit - lowlimit + 1) * random;
- end;
-
- (*
- * returns true if a random number, weighted by the difficulty level, is
- * less than the argument
- *)
-
- function unlucky(percentchance : real) : boolean;
-
- begin
- unlucky := rand(0.0, 1.0 - chance) <= percentchance;
- end;
-
- (*
- * converts a numerical ascii character to its corresponding integral value
- *)
-
- function asciitoint(digit : char) : integer;
-
- begin
- asciitoint := ord(digit) - ord('0');
- end;
-
- (*
- * returns true if the argument is a numerical digit
- *)
-
- function isdigit(ch : char) : boolean;
-
- begin
- isdigit := (ch >= '0') and (ch <= '9');
- end;
-
- (*
- * convert determines the numerical value of the digits ina string. it returns
- * the integer and updates the string to now contain whatever was after the
- * end of the number. if the string is blank, the value is zero; if a number
- * is not found it returns -1.
- *)
-
- function convert(numstring : str80) : integer;
-
- var
- intvalue : integer;
- position : integer;
- digitsfound : integer;
- endofnumber : boolean;
- notinteresting : boolean;
-
- begin
- intvalue := 0;
- digitsfound := 0;
- position := 1;
- endofnumber := false;
- notinteresting := true;
- if length(numstring) > 0 then
- begin
- while (position < length(numstring)) and notinteresting do
- if numstring[position] = ' ' then
- position := position + 1
- else
- notinteresting := false;
- while (position <= length(numstring)) and (not endofnumber) do
- if isdigit(numstring[position]) then
- begin
- intvalue := intvalue * 10 + asciitoint(numstring[position]);
- position := position + 1;
- digitsfound := digitsfound + 1;
- end
- else
- endofnumber := true;
- if digitsfound = 0 then
- intvalue := -1;
- end;
- convert := intvalue;
- end;
-
- (*
- * asks a question with a single character answer. if the response is in the
- * set 'answers', the letter is returned. otherwise the string ifbad is
- * printed and the question is asked again.
- *)
-
- function ask(question, ifbad : str80; responses : answers) : char;
-
- var
- bad : boolean;
- ch : char;
-
- begin
- bad := true;
- repeat
- write(question);
- readln(ch);
- writeln;
- if ch in responses then
- bad := false
- else
- writeln(ifbad);
- until not bad;
- ask := ch;
- end;
-
- (*
- * prints out the instructions from a file instrfile
- *)
-
- procedure instructions;
-
- var
- instruct : text;
- ch : char;
- str : string[80];
-
- begin
- assign(instruct,instrfile);
- reset(instruct);
- while not eof(instruct) do
- begin
- readln(instruct,str);
- writeln(str);
- end;
- end;
-
- procedure startup;
-
- begin
- if ask('Do you want instructions? ','Please answer Y or N',['Y','N']) = 'Y' then
- instructions;
- randomize;
- end;
-
- (*
- * ask the player for the difficulty level of the next landing
- *)
-
- procedure getdifficulty;
-
- var
- level : char;
-
- begin
- level := ask('Level of difficulty? ','B:Beginner, E:Expert, N:Navigator, A:Astronaut',
- ['B','E','N','A']);
- case level of
- 'B' : chance := slightly;
- 'E' : chance := moderately;
- 'N' : chance := very;
- 'A' : chance := impossible;
- end;
- end;
-
- (*
- * variables that must be re-set each time a new landing is attempted
- *)
-
- procedure startgame;
-
- begin
- getdifficulty;
- gravity := rand(9.0 + chance, 11.0 + chance);
- height := rand(1.0 + chance, 2.0 + chance) * 100.0;
- speed := rand(0.0, 100.0 * chance) + 30.0;
- fuel := round(50.0 * rand(3.0 - chance, 4.0 - chance));
- maxlandingspeed := crashlandspeed - 10.0 * chance;
- misschance := certainty;
- ranout := false;
- end;
-
- (*
- * tell player his height, speed and direction
- *)
-
- procedure writestatus;
-
- begin
- writeln;
- write('You are ');
- if speed > 0.0 then
- write('falling')
- else
- write('rising');
- writeln(' from a height of ',height:1:1);
- writeln('meters at ',abs(speed):1:1,' m/s.');
- if not ranout then
- writeln('There are ',fuel:1,' liters of fuel left.');
- ranout := fuel = 0;
- end;
-
- (*
- * determines if there are any meteors, and if so, how many
- *)
-
- procedure lookformeteors;
-
- var
- eachrock : integer;
-
- begin
- misschance := certainty;
- if unlucky(0.1) then
- begin
- nummeteors := round(rand(minmeteors,maxmeteors + 10.0 * chance));
- for eachrock := 1 to nummeteors do
- misschance := misschance * eachmisschance;
- writeln('We are on a collision course with ',nummeteors:1);
- write('meteors.');
- if ranout then
- writeln
- else
- begin
- writeln('If we do not use more than ',minavoid:1,'liters of fuel in the');
- writeln('next second, there is a ',round(100.0*(1.0-misschance)),
- ' % probability that we will be');
- writeln('hit. If more is used it will be only 10 %.');
- end;
- end;
- end;
-
- (*
- * asks the player for the amount of fuel to use in the next time period.
- *)
-
- procedure getburn;
-
- const
- fuelprompt = 'Units of fuel : ';
-
- begin
- repeat
- write(fuelprompt);
- readln(inp);
- burn := convert(inp);
- if burn > fuel then
- writeln('There isn''t that much fuel left.')
- else if burn < 0 then
- writeln('I don''t think that''s possible.');
- until (burn <= fuel) and (burn >= 0);
- end;
-
- (*
- * figure out the craft's new speed according to the laws of physics
- *)
-
- procedure updatestatus;
-
- var
- deltat : integer;
-
- begin
- fuel := fuel - burn;
- deltat := 0;
- repeat
- deltat := deltat + 1;
- height := height - speed * timeinc - (gravity - burn) * 0.5 * sqr(timeinc);
- speed := speed + (gravity - burn) * timeinc;
- until (deltat = trunc(1 / timeinc)) or (height <= landingheight);
- end;
-
- (*
- * all the procedures that make a turn
- *)
-
- procedure doaturn;
-
- begin
- writestatus;
- lookformeteors;
- if fuel > 0 then
- getburn
- else
- burn := 0;
- updatestatus;
- end;
-
- (*
- * the course has changed: meteors have a lower chance of hitting
- *)
-
- function coursechanged : boolean;
-
- begin
- if unlucky(0.1) then
- begin
- writeln('Despite the precautionary measures taken, the ship was destroyed.');
- coursechanged := true;
- end
- else
- begin
- writeln('Your prudent actions saved the ship from the menacing meteors!');
- coursechanged := false;
- end
- end;
-
- function coursesame: boolean;
-
- begin
- if not unlucky(1.0 - misschance) then
- begin
- writeln('Your piloting skills have steered you through the center of the swarm!');
- coursesame := false;
- end
- else if ranout then
- begin
- writeln('What a pity .. your craft was demolished by meteors before it could');
- writeln('be vaporized on contact with the surface.');
- coursesame := true;
- end
- else
- begin
- writeln('Your pointless gambling has destroyed the ship, you foolish plebe!');
- coursesame := true;
- end;
- end;
-
- (*
- * figures if any meteors (if there were any) managed to hit the ship.
- * different messages are printed depending on the thrust of the last turn.
- *)
-
-
- function anyhit : boolean;
-
- begin
- if (misschance = certainty) or (height <= landingheight) then
- anyhit := false
- else if burn > minavoid then
- anyhit := coursechanged
- else
- anyhit := coursesame;
- end;
-
- (*
- * returns true if the ship has come close enough to the ground that we can
- * say it has landed. could crash or touch down safely.
- *)
-
- function landed : boolean;
-
- begin
- if height < landingheight then
- begin
- speed := abs(speed);
- if speed < maxlandingspeed then
- write('We have landed safely')
- else
- write('We have crashed');
- writeln(' at a speed of ',speed:1:1,' meters/second.');
- landed := true;
- end
- else
- landed := false;
- end;
-
-
- begin
- startup;
- repeat
- startgame;
- repeat
- doaturn;
- until landed or anyhit;
- until ask('Again? ','Y or N',['Y','N']) = 'N';
- writeln('Bye!');
- end.
-
-
-
-